<?php
/**
 * A database driver for the MySQL database.
 *
 * A driver must extend Database_Driver_Abstract and implement the Database_Driver interface.
 */
class Database_Driver_Mysql extends Database_Driver_Abstract implements Database_Driver {
    /**
     * The database hostname.
     * @var string
     */
    protected $hostname = '';
    /**
     * The username for the database.
     * @var string
     */
    protected $username = '';
    /**
     * The password for the database.
     * @var string
     */
    protected $password = '';
    /**
     * The database name.
     * @var string
     */
    protected $dbname = '';
    protected $numrows = false;

    /**
     * Set up this object from a Config_Section object.
     * @param Config_Section $config
     */
    public function __construct(Config_Section $config) {
        parent::__construct();
        $this->drivername = $config->driver;
        $this->hostname = $config->hostname;
        $this->username = $config->username;
        $this->password = $config->password;
        $this->dbname = $config->database;
    }

    /**
     * Get the driver's name.
     * @return string
     */
    public function getDriverName() {
        return $this->drivername;
    }

    /**
     * Connect to the database.
     * @throws Database_Exception
     */
    public function connect() {
        if(!$this->connection) {
            $this->connection = @mysql_connect($this->hostname, $this->username, $this->password, true);
            if(!$this->connection) {
                throw new Database_Exception('Connection failed: ' . mysql_error());
            }
            if(!mysql_select_db($this->dbname, $this->connection)) {
                throw new Database_Exception("Can not access database '" . $this->dbname . "'.");
            }
        }
    }

    /**
     * Take and store a query for later.
     * 
     * @param string $sql
     * @throws Database_Exception
     */
    public function prepare($sql) {
        if(!is_string($sql) || empty($sql)) {
            throw new Database_Exception('Query is empty or not a string.');
        }
        $this->query = $sql;
    }
    
    /**
     * Execute an SQL query.
     * @throws Database_Exception
     */
    public function execute($params = array()) {
        if(empty($this->query)) {
            throw new Database_Exception('No query prepared.');
        }
        $runsql = $this->query;
        foreach($params as $param) {
            $runsql = preg_replace('/\?/', $this->quote($param), $runsql, 1);
        }
        $this->connect();
        $this->result = mysql_query($runsql, $this->connection);
        if(!$this->result) {
            throw new Database_Exception("Query error: " . mysql_error());
        }
        return $this->fetchAll();
    }

    /**
     * Run a query.
     * @throws Database_Exception
     */
    public function query($sql) {
        $this->query = $sql;
        return $this->execute();
    }
    
    public function escapeString($string) {
        $this->connect();
        return mysql_real_escape_string($string, $this->connection);
    }
    
    public function quote($string) {
        if($string instanceof Database_Expr) {
            return (string)$string;
        }
        $string = $this->escapeString($string);
        if(!is_numeric($string)) {
            $string = "'" . $string . "'";
        }
        return $string;
    }
    
    public function numRows() {
        if(!$this->numrows) {
            if($this->result) {
                $this->numrows = mysql_numrows($this->result);
            }
        }
        return $this->numrows;
    }

    public function fetchAll() {
        $data = array();
        while($record = mysql_fetch_assoc($this->result)) {
            $data[] = $record;
        }
        return $data;
    }
    
    public function selectAll($table) {
        return $this->query('SELECT * FROM ' . $table);
    }
    
    public function insert($table, $data) {
        $this->query("INSERT INTO $table () VALUES ()");
        return mysql_insert_id($this->connection);
    }
    
    public function update($table, $data, $where) {
        $this->query("UPDATE $table SET ");
    }
}
?>